-- ********************************************************
-- Author: (c) Petr Klička - 2020 (petrkl12)
-- PHILIPS HUE SUPPORT FOR FIBARO HC3 - MAIN QA DEVICE
-- ********************************************************

-- TERMS AND CONDITIONS:
-- Permission to use, copy, modify, and distribute this software and its documentation for
-- educational, research, personal use and non-profit purposes,without fee and without a signed
-- licensing agreement, is hereby granted, provided that the above copyright notice, with "Terms
-- and Conditions" and "Disclaimer" appear in all copies, modifications, and distributions.
-- It is strictly forbidden to sell, rent, lease and/or lend this software for profit without prior
-- consent from the Author. Please contact the Author by email: petrkl12@gmail.com for commercial 
-- licensing opportunities.

-- DISCLAIMER:
-- This software is provided by copyright owner "as is" and any express or implied warranties,
-- including, but not limited to, the implied warranties of merchantability and fitness for a
-- particular purpose are disclaimed. In no event shall the author and distributor be liable for any
-- direct, indirect, incidental, special, exemplary, or consequential damages (including, but not
-- limited to, procurement of substitute goods or services; loss of use, data, or profits; or
-- business interruption) however caused and on any theory of liability, whether in contract,
-- strict liability, or tort (including negligence or otherwise) arising in any way out of the use of
-- this software, even if advised of the possibility of such damage.

--[[
-- QAID_HueMain and QAID_HueLight have to be numbers
-- light on
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='on', deviceID=QAID_HueLight})
-- light on with transition time
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='on', deviceID=QAID_HueLight, transitiontime=0})
-- light off
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='off', deviceID=QAID_HueLight})
-- light on with transition time
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='off', deviceID=QAID_HueLight, transitiontime=0})
-- light on with setting of brightness (in value), if value<2 then value=100, value=<0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='on_bri', deviceID=QAID_HueLight, value=50})
-- setup of brightness (in value) and also if value is 0 then Light off - in other cases Light on, value=<0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='brightness', deviceID=QAID_HueLight, value=50})
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='brightness', deviceID=QAID_HueLight, value=50, transitiontime=0})
-- light toggle based on last refreshed data from hue bridge (fast method, in some cases can be inaccurate)
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='toggle', deviceID=QAID_HueLight})
-- light toggle based on new request from hue bridge (slower method but accurate)
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='toggle2', deviceID=QAID_HueLight})
-- light toggle based on last refreshed data from hue bridge (fast method, in some cases can be inaccurate), brightness is in value <0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='toggle_bri', deviceID=QAID_HueLight, value=50})
-- light toggle based on new request from hue bridge (slower method but accurate), brightness is in value <0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='toggle_bri2', deviceID=QAID_HueLight, value=50})
-- setup of color (in value), value=<0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='color', deviceID=QAID_HueLight, value=50})
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='color', deviceID=QAID_HueLight, value=50, transitiontime=0})
-- setup of saturation (in value), value=<0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='saturation', deviceID=QAID_HueLight, value=50})
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='saturation', deviceID=QAID_HueLight, value=50, transitiontime=0})
-- setup of color temperature (in value), value=<0,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='colortemp', deviceID=QAID_HueLight, value=50})
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='colortemp', deviceID=QAID_HueLight, value=50, transitiontime=0})
-- setup of color via RGB (in colorR, colorB, colorB <0,254>), brightness is in value=<2,100>
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='colorRGB', deviceID=QAID_HueLight, colorR=10, colorG=200, colorB=100, value=100})
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='colorRGB', deviceID=QAID_HueLight, colorR=10, colorG=200, colorB=100, value=50, transitiontime=0})
-- setup of hue light based on global setting in Hue Main for button Color 1 to button Color 5
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='setcolor', deviceID=QAID_HueLight, typebutton='color1'})
-- setup of hue light based on global setting in Hue Main for favourite button 1 to button 5
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='setbutton', deviceID=QAID_HueLight, typebutton='button5'})
-- setup of hue light based on standard Philips Hue commands and values
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='set', deviceID=QAID_HueLight, ParamHue={"on":true,"hue":0,"sat":254,"bri":254}})
fibaro.call(QAID_HueMain, "HueCommands", {type='Hue', action='set', deviceID=QAID_HueLight, ParamHue={"on":true,"bri":254,"xy":[0.3651,0.3719]}})
--]]

_HueMainQAVersionNumber="2.55"_HueMainQAVersionDate="28.9.2020"_HueMainQAVersionType="MainHue"MinimumHueQAVer={LightStandard=1.30,TemperatureStandard=1.30,MotionStandard=1.30,LightSensorStandard=1.30,SwitchStandard=1.30}local a="5.040.37"if dofile then if not hc3_emulator then hc3_emulator={id=21,quickApp=true,poll=1500}dofile("fibaroapiHC3.lua")end;hc3_emulator.FILE("QA_Hue_F_Tools.lua","HueTools")hc3_emulator.FILE("QA_Hue_F_Language.lua","HueLanguages")hc3_emulator.FILE("QA_Hue_F_Active.lua","HueActive")hc3_emulator.FILE("QA_Hue_F_MainUpdate.lua","HueMainUpdate")hc3_emulator.FILE("QA_Hue_F_Menu.lua","HueMenu")hc3_emulator.FILE("QA_Hue_F_HueInfo.lua","HueInfo")end;__TAG="QA_HUE_MAIN_"..tostring(plugin.mainDeviceId)LanguageQA=""QAErrors,QALightsInfo,HueDefBridges,HueBridges,BridgeEmptyUser,GlobalHueQA,GlobalHueQAind,GlobalHuePowerQA,GlobalHueScenesforQA,LanguageDefLights,DescriptionAddLights,LanguageDefSensors,DescriptionAddSensors,FavouriteColor,FavouriteButton,QAHueIcon,DefLabels,http_header,OptionsHGet={},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}RunQA,RunQAInit=false,false;thisDeviceID=plugin.mainDeviceId;GlobalStatusMessage,LastUpdateHMain,oldLastUpdateHMain="","",""HueMainMagicNumber="A24Uj8756"CallWait,CallWaitHue,_HueTimeout,ShowBridgeError=1,20,30000,5;allowExtraHueUpdate,stopUpdateBridges,RunHueMain=true,false,false;RunTimeStart,SumPwrTimer,PowerUpdateInterval=nil;SettingValHueCM={hs={on=true,bri=true,alert=true,effect=true,hue=true,sat=true},xy={on=true,bri=true,alert=true,effect=true,xy=true},ct={on=true,bri=true,alert=true,effect=true,ct=true},other={on=true,bri=true,alert=true,effect=true}}LanguageDefition()function SetGlobalVar(self)RunHueMain=false;local b="HueMainID_"..HueMainMagicNumber;if checkGlobalVar(b)then local c=fibaro.getGlobalVariable(b)if tostring(c)~=tostring(thisDeviceID)then fibaro.setGlobalVariable(b,tostring(thisDeviceID))end else api.post("/globalVariables/",{name=b})fibaro.setGlobalVariable(b,tostring(thisDeviceID))end;GlobalStatusMessage,LastUpdateHMain="",""QAErrors,QALightsInfo,HueDefBridges,HueBridges,GlobalHueQA,GlobalHueQAind,GlobalHuePowerQA,GlobalHueScenesforQA,BridgeEmptyUser={},{},{},{},{},{},{},{},{}http_header={['Connection']='keep-alive',['User-Agent']='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36',['Accept']='text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',['Accept-Encoding']='identity',['Accept-Language']='en-US,en;q=0.5'}OptionsHGet={headers=http_header,method='GET',timeout=_HueTimeout or 30000}LanguageQA=tostring(self:getVariable("Language")):lower()if LanguageDefLights and LanguageDefLights[LanguageQA]==nil then LanguageQA="en"end;if LanguageDefSensors and LanguageDefSensors[LanguageQA]==nil then LanguageQA="en"end end;function UserHueBridgesDefinitions(self)local d,e;local f={'"on":true,"hue":0,"sat":254,"bri":127','"on":true,"hue":5996,"sat":254,"bri":127','"on":true,"hue":9209,"sat":254,"bri":127','"on":true,"hue":21845,"sat":254,"bri":63','"on":true,"hue":43690,"sat":254,"bri":127'}local g={'"on":true,"bri":254,"xy":[0.4578,0.41]','"on":true,"bri":144,"xy":[0.5019,0.4152]','"on":true,"bri":1,"xy":[0.561,0.4042]','"on":true,"bri":254,"xy":[0.3143,0.3301]','"on":true,"bri":254,"xy":[0.3651,0.3719]'}FavouriteColor={}for h=1,5 do d=self:getVariable("FavouriteColor"..tostring(h))e="color"..tostring(h)if d and tostring(d)~=""and tostring(d):lower()~="none"then FavouriteColor[e]=tostring(d)else FavouriteColor[e]=f[h]end end;FavouriteButton={}for h=1,5 do d=self:getVariable("FavouriteButt"..tostring(h))e="button"..tostring(h)if d and tostring(d)~=""and tostring(d):lower()~="none"then FavouriteButton[e]=tostring(d)else FavouriteButton[e]=g[h]end end end;function IconsForHueQA(self)local i={"IconLightSensor","IconTemperature","IconMotion","IconLight","IconSwZLL","IconSwZLLOn","IconSwZLLDUp","IconSwZLLDDown","IconSwZLLOff","IconSwZGP","IconSwZGPBtn1","IconSwZGPBtn2","IconSwZGPBtn3","IconSwZGPBtn4"}QAHueIcon={}local j;for h=1,#i do j=self:getVariable(i[h])if j and tonumber(j)and tonumber(j)>0 then QAHueIcon[i[h]]=tonumber(j)end end end;function AddBridge(self,k,l,m,n,o,p)HueDefBridges[#HueDefBridges+1]={BridgeName=k}local q=k.."Sensors"HueBridges[q]={HueUrl='http://'..l..'/api/'..m..'/sensors',IPhueBridge=l,HueUser=m,BridgeInitDone=false,BridgeInitRun=false,SceneInitDone=true,SceneInitRun=false,BridgeError=false,BridgeErrorNum=0,TypeOfBridge="sensors",BridgeName=q,BridgeMainName=k,PUTCommand="",HueIDfromQA={},QAfromHueID={},UpdateInterval=n}q=k.."LGroups"HueBridges[q]={HueUrl='http://'..l..'/api/'..m..'/groups',IPhueBridge=l,HueUser=m,BridgeInitDone=false,BridgeInitRun=false,SceneInitDone=false,SceneInitRun=false,BridgeError=false,BridgeErrorNum=0,TypeOfBridge="lgroups",BridgeName=q,BridgeMainName=k,PUTCommand="action",HueIDfromQA={},QAfromHueID={},HueLightsforVD={},UpdateInterval=o}q=k.."Lights"HueBridges[q]={HueUrl='http://'..l..'/api/'..m..'/lights',IPhueBridge=l,HueUser=m,BridgeInitDone=false,BridgeInitRun=false,SceneInitDone=false,SceneInitRun=false,BridgeError=false,BridgeErrorNum=0,TypeOfBridge="lights",BridgeName=q,BridgeMainName=k,PUTCommand="state",HueIDfromQA={},QAfromHueID={},GroupVDsforHueLight={},UpdateInterval=p}end;function AddBridgeEmptyUser(self,k,l,r)local s={BridgeName=k,HueUrl='http://'..l..'/api',IPhueBridge=l,HueUser="",UserNameCode=r}BridgeEmptyUser[#BridgeEmptyUser+1]=s end;function CreateListofHueBridges(self)local t=api.get('/devices/'..tostring(thisDeviceID))if t==nil or t.properties.quickAppVariables==nil then return end;local u,v,w,x,y={},0,false,2000,300;for z,A in ipairs(t.properties.quickAppVariables)do u[A.name]=A.value end;if u["UpdateLights"]then x=tonumber(u["UpdateLights"])end;if u["UpdateSensors"]then y=tonumber(u["UpdateSensors"])end;local B,C,D,E;repeat v=v+1;E=tostring(v)B=u["HueBridgeName"..E]C=u["HueBridgeIP"..E]local F="HueUser"..E;D=u[F]if B and C and D then if tostring(B)~=""and TestAscii(B)and tostring(B):lower()~="none"and tostring(C)~=""and tostring(C):lower()~="none"then if tostring(D)~=""and tostring(D):lower()~="none"and tostring(D):len()==40 then AddBridge(self,B,C,D,y,x,x)else AddBridgeEmptyUser(self,B,C,F)end end else w=true end until w end;function GetID_GlobalHueQAind(G)if G==nil then return nil end;local H=tostring(G)local I;for h=1,#GlobalHueQAind do if GlobalHueQAind[h].QA_ID==H then I=h;break end end;return I end;function DeleteQAFromBridge(self,G)if G==nil then return end;local J=tostring(G)if GlobalHueQA[J]==nil then return end;local q=GlobalHueQA[J].bridge;local K=GlobalHueQA[J].hueID;if GlobalHuePowerQA[J]then GlobalHuePowerQA[J]=nil end;if HueBridges[q].HueIDfromQA[J]then HueBridges[q].HueIDfromQA[J]=nil end;if GlobalHueQA[J]then GlobalHueQA[J]=nil end;if GlobalHueScenesforQA[J]then GlobalHueScenesforQA[J]=nil end;local L={}for h=1,#GlobalHueQAind do if GlobalHueQAind[h].QA_ID~=J then L[#L+1]=GlobalHueQAind[h]end end;GlobalHueQAind=L;if HueBridges[q].QAfromHueID[K]then if#HueBridges[q].QAfromHueID[K]<2 then HueBridges[q].QAfromHueID[K]=nil else local M={}for h=1,#HueBridges[q].QAfromHueID[K]do if HueBridges[q].QAfromHueID[K][h]~=J then M[#M+1]=HueBridges[q].QAfromHueID[K][h]end end;HueBridges[q].QAfromHueID[K]=M end end;if HueBridges[q].TypeOfBridge=="lgroups"then if HueBridges[q].HueLightsforVD then local N=HueBridges[q].HueLightsforVD[J]if N then local O=HueBridges[q].BridgeMainName.."Lights"for z,K in pairs(N)do if#HueBridges[O].GroupVDsforHueLight[K]<2 then HueBridges[O].GroupVDsforHueLight[K]=nil else local P={}for h=1,#HueBridges[O].GroupVDsforHueLight[K]do if HueBridges[O].GroupVDsforHueLight[K][h]~=J then P[#P+1]=HueBridges[O].GroupVDsforHueLight[K][h]end end;HueBridges[O].GroupVDsforHueLight[K]=P end end;HueBridges[q].HueLightsforVD[J]=nil end end end;self:updateLabelBridge()self:updateLabelUpdateQA()end;function ReadIconsForSwitch(Q)local i={"IconSwZLL","IconSwZLLOn","IconSwZLLDUp","IconSwZLLDDown","IconSwZLLOff","IconSwZGP","IconSwZGPBtn1","IconSwZGPBtn2","IconSwZGPBtn3","IconSwZGPBtn4"}local R,S={},0;local j;for h=1,#i do if Q[i[h]]then j=Q[i[h]]if tonumber(j)and tonumber(j)>0 then R[i[h]]=tonumber(j)S=S+1 end end end;if S==0 then R=nil end;return R end;function UpdateQAInBridge(self,Q,G,T)if Q==nil or G==nil or Q=={}then return end;local J=tostring(G)if GlobalHueQA[J]==nil then AddQAToBridge(self,Q,J,T)else local u={}for z,A in ipairs(Q)do u[A.name]=A.value end;local q=""local U,V,W,X,Y,Z,_,a0,a1=nil,"01.01.2020",0,0,false,false,false,0,nil;local a2,a3,a4,K,a5,a6;local a7=tostring(fibaro.getRoomNameByDeviceID(tonumber(J))).."-"..tostring(fibaro.getName(tonumber(J)))if u["HueMagicNumber"]then if u["HueMagicNumber"]==HueMainMagicNumber then if u["HueBridge"]and TestAscii(u["HueBridge"])then if u["VersionType"]then U=u["VersionType"]end;if u["VersionDate"]then V=u["VersionDate"]end;if u["VersionNumber"]and tonumber(u["VersionNumber"])and tonumber(u["VersionNumber"])>0 then W=tonumber(u["VersionNumber"])end;if U==nil or V==nil or W==nil then U,V,W=nil,nil,nil end;if u["MinHueMainVer"]and tonumber(u["MinHueMainVer"])and tonumber(u["MinHueMainVer"])>0 then X=tonumber(u["MinHueMainVer"])end;if not(tonumber(_HueMainQAVersionNumber)>=X)then a0=a0+1 end;if MinimumHueQAVer[U]and not(W>=MinimumHueQAVer[U])then a0=a0+2 end;if u["AutomaticUpdate"]then local a8=string.lower(tostring(u["AutomaticUpdate"]))if a8=="yes"or a8=="y"then Y=true end end;if u["IconUpdate"]then local a8=string.lower(tostring(u["IconUpdate"]))if a8=="yes"or a8=="y"then Z=true end end;if u["Logs"]then local a8=string.lower(tostring(u["Logs"]))if a8=="yes"or a8=="y"then _=true end end;if u["HueGroupID"]and tonumber(u["HueGroupID"])and tonumber(u["HueGroupID"])>=0 then q=u["HueBridge"].."LGroups"K=tostring(u["HueGroupID"])if u["PowerMin"]then if tonumber(u["PowerMin"])and tonumber(u["PowerMin"])>=0 then a2=tonumber(u["PowerMin"])elseif u["PowerMin"]=="Default"or u["PowerMin"]=="D"or u["PowerMin"]=="Def"then a2="D"end end;if u["PowerMax"]then if tonumber(u["PowerMax"])and tonumber(u["PowerMax"])>=0 then a3=tonumber(u["PowerMax"])elseif u["PowerMax"]=="Default"or u["PowerMax"]=="D"or u["PowerMax"]=="Def"then a3="D"end end;if u["ShowBulbs"]then local a8=string.lower(tostring(u["ShowBulbs"]))if a8=="yes"or a8=="y"then a1=true end;if a8=="no"or a8=="n"then a1=false end end elseif u["HueLightID"]and tonumber(u["HueLightID"])and tonumber(u["HueLightID"])>0 then q=u["HueBridge"].."Lights"K=tostring(u["HueLightID"])if u["PowerMin"]then if tonumber(u["PowerMin"])and tonumber(u["PowerMin"])>=0 then a2=tonumber(u["PowerMin"])elseif u["PowerMin"]=="Default"or u["PowerMin"]=="D"or u["PowerMin"]=="Def"then a2="D"end end;if u["PowerMax"]then if tonumber(u["PowerMax"])and tonumber(u["PowerMax"])>=0 then a3=tonumber(u["PowerMax"])elseif u["PowerMax"]=="Default"or u["PowerMax"]=="D"or u["PowerMax"]=="Def"then a3="D"end end;if u["ShowBulbs"]then local a8=string.lower(tostring(u["ShowBulbs"]))if a8=="yes"or a8=="y"then a1=true end;if a8=="no"or a8=="n"then a1=false end end elseif u["HueSensorID"]and tonumber(u["HueSensorID"])and tonumber(u["HueSensorID"])>0 then q=u["HueBridge"].."Sensors"K=tostring(u["HueSensorID"])if u["TempCorrection"]and tonumber(u["TempCorrection"])then a4=tonumber(u["TempCorrection"])end;if U=="SwitchStandard"then a5=ReadIconsForSwitch(u)if u["IconReset"]and tonumber(u["IconReset"])and tonumber(u["IconReset"])>0 then a6=tonumber(u["IconReset"])end end end end end end;if K and q~=""and HueBridges[q]then if q==GlobalHueQA[J].bridge and K==GlobalHueQA[J].hueID then GlobalHueQA[J]={bridge=q,hueID=K,descr=a7,versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}if a2 and a3 then if a2=="D"or a3=="D"then GlobalHuePowerQA[J]={powerCurrent=0,powerMin="D",powerMax="D"}elseif not(a2==0 and a3==0)then GlobalHuePowerQA[J]={powerCurrent=0,powerMin=a2,powerMax=a3}end end;if u["ShowBulbs"]then GlobalHueQA[J]["showBulbs"]=a1 end;if a4 then GlobalHueQA[J]["tempCorrection"]=a4 end;if a5 then GlobalHueQA[J]["iconsSwitch"]=a5 end;if a6 then GlobalHueQA[J]["iconReset"]=a6 end;local a9=GetID_GlobalHueQAind(G)if a9 then GlobalHueQAind[a9]={bridge=q,QA_ID=J,hueID=K,descr=a7,descrAscii=string.lower(OnlyAscii(a7)),versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}else GlobalHueQAind[#GlobalHueQAind+1]={bridge=q,QA_ID=J,hueID=K,descr=a7,descrAscii=string.lower(OnlyAscii(a7)),versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}end else DeleteQAFromBridge(self,J)HueBridges[q].HueIDfromQA[J]=K;if HueBridges[q].QAfromHueID[K]==nil then HueBridges[q].QAfromHueID[K]={}end;table.insert(HueBridges[q].QAfromHueID[K],J)GlobalHueQA[J]={bridge=q,hueID=K,descr=a7,versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}GlobalHueScenesforQA[J]={numsc=0,scenes={}}GlobalHueQAind[#GlobalHueQAind+1]={bridge=q,QA_ID=J,hueID=K,descr=a7,descrAscii=string.lower(OnlyAscii(a7)),versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}if a2 and a3 then if a2=="D"or a3=="D"then GlobalHuePowerQA[J]={powerCurrent=0,powerMin="D",powerMax="D"}elseif not(a2==0 and a3==0)then GlobalHuePowerQA[J]={powerCurrent=0,powerMin=a2,powerMax=a3}end end;if u["ShowBulbs"]then GlobalHueQA[J]["showBulbs"]=a1 end;if a4 then GlobalHueQA[J]["tempCorrection"]=a4 end;if a5 then GlobalHueQA[J]["iconsSwitch"]=a5 end;if a6 then GlobalHueQA[J]["iconReset"]=a6 end;ScenesUpdateOneQA(self,J,0)end else DeleteQAFromBridge(self,J)end end end;function AddQAToBridge(self,Q,G,T)if Q==nil or G==nil or Q=={}then return end;local J=tostring(G)if GlobalHueQA[J]then UpdateQAInBridge(self,Q,J,T)else local u={}for z,A in ipairs(Q)do u[A.name]=A.value end;if u["HueMagicNumber"]then if u["HueMagicNumber"]==HueMainMagicNumber then if u["HueBridge"]and TestAscii(u["HueBridge"])then local q=""local U,V,W,X,Y,Z,_,a0,a1=nil,"01.01.2020",0,0,false,false,false,0,nil;local a2,a3,a4,K,a5,a6;local a7=tostring(fibaro.getRoomNameByDeviceID(tonumber(J))).."-"..tostring(fibaro.getName(tonumber(J)))if u["VersionType"]then U=u["VersionType"]end;if u["VersionDate"]then V=u["VersionDate"]end;if u["VersionNumber"]and tonumber(u["VersionNumber"])and tonumber(u["VersionNumber"])>0 then W=tonumber(u["VersionNumber"])end;if U==nil or V==nil or W==nil then U,V,W=nil,nil,nil end;if u["MinHueMainVer"]and tonumber(u["MinHueMainVer"])and tonumber(u["MinHueMainVer"])>0 then X=tonumber(u["MinHueMainVer"])end;if not(tonumber(_HueMainQAVersionNumber)>=X)then a0=a0+1 end;if MinimumHueQAVer[U]and not(W>=MinimumHueQAVer[U])then a0=a0+2 end;if u["AutomaticUpdate"]then local a8=string.lower(tostring(u["AutomaticUpdate"]))if a8=="yes"or a8=="y"then Y=true end end;if u["IconUpdate"]then local a8=string.lower(tostring(u["IconUpdate"]))if a8=="yes"or a8=="y"then Z=true end end;if u["Logs"]then local a8=string.lower(tostring(u["Logs"]))if a8=="yes"or a8=="y"then _=true end end;if u["HueGroupID"]and tonumber(u["HueGroupID"])and tonumber(u["HueGroupID"])>=0 then q=u["HueBridge"].."LGroups"K=tostring(u["HueGroupID"])if u["PowerMin"]then if tonumber(u["PowerMin"])and tonumber(u["PowerMin"])>=0 then a2=tonumber(u["PowerMin"])elseif u["PowerMin"]=="Default"or u["PowerMin"]=="D"or u["PowerMin"]=="Def"then a2="D"end end;if u["PowerMax"]then if tonumber(u["PowerMax"])and tonumber(u["PowerMax"])>=0 then a3=tonumber(u["PowerMax"])elseif u["PowerMax"]=="Default"or u["PowerMax"]=="D"or u["PowerMax"]=="Def"then a3="D"end end;if u["ShowBulbs"]then local a8=string.lower(tostring(u["ShowBulbs"]))if a8=="yes"or a8=="y"then a1=true end;if a8=="no"or a8=="n"then a1=false end end elseif u["HueLightID"]and tonumber(u["HueLightID"])and tonumber(u["HueLightID"])>0 then q=u["HueBridge"].."Lights"K=tostring(u["HueLightID"])if u["PowerMin"]then if tonumber(u["PowerMin"])and tonumber(u["PowerMin"])>=0 then a2=tonumber(u["PowerMin"])elseif u["PowerMin"]=="Default"or u["PowerMin"]=="D"or u["PowerMin"]=="Def"then a2="D"end end;if u["PowerMax"]then if tonumber(u["PowerMax"])and tonumber(u["PowerMax"])>=0 then a3=tonumber(u["PowerMax"])elseif u["PowerMax"]=="Default"or u["PowerMax"]=="D"or u["PowerMax"]=="Def"then a3="D"end end;if u["ShowBulbs"]then local a8=string.lower(tostring(u["ShowBulbs"]))if a8=="yes"or a8=="y"then a1=true end;if a8=="no"or a8=="n"then a1=false end end elseif u["HueSensorID"]and tonumber(u["HueSensorID"])and tonumber(u["HueSensorID"])>0 then q=u["HueBridge"].."Sensors"K=tostring(u["HueSensorID"])if u["TempCorrection"]and tonumber(u["TempCorrection"])then a4=tonumber(u["TempCorrection"])end;if U=="SwitchStandard"then a5=ReadIconsForSwitch(u)if u["IconReset"]and tonumber(u["IconReset"])and tonumber(u["IconReset"])>0 then a6=tonumber(u["IconReset"])end end end;if K and q~=""and HueBridges[q]then HueBridges[q].HueIDfromQA[J]=K;if HueBridges[q].QAfromHueID[K]==nil then HueBridges[q].QAfromHueID[K]={}end;table.insert(HueBridges[q].QAfromHueID[K],J)GlobalHueQA[J]={bridge=q,hueID=K,descr=a7,versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}GlobalHueScenesforQA[J]={numsc=0,scenes={}}GlobalHueQAind[#GlobalHueQAind+1]={bridge=q,QA_ID=J,hueID=K,descr=a7,descrAscii=string.lower(OnlyAscii(a7)),versionType=U,versionDate=V,versionNumber=W,automaticUpdate=Y,minVerHueMain=X,updateQA=a0,iconUpdate=Z,QAtype=T}if a2 and a3 then if a2=="D"or a3=="D"then GlobalHuePowerQA[J]={powerCurrent=0,powerMin="D",powerMax="D"}elseif not(a2==0 and a3==0)then GlobalHuePowerQA[J]={powerCurrent=0,powerMin=a2,powerMax=a3}end end;if u["ShowBulbs"]then GlobalHueQA[J]["showBulbs"]=a1 end;if a4 then GlobalHueQA[J]["tempCorrection"]=a4 end;if a5 then GlobalHueQA[J]["iconsSwitch"]=a5 end;if a6 then GlobalHueQA[J]["iconReset"]=a6 end end end end end end end;function CreateListofHueDev(self)local aa=api.get('/devices')local ab=tostring(thisDeviceID)for z,t in ipairs(aa)do if t.visible and t.properties.quickAppVariables and tostring(t.id)~=ab then AddQAToBridge(self,t.properties.quickAppVariables,t.id,t.type)end end;table.sort(GlobalHueQAind,function(ac,ad)return ac.descrAscii<ad.descrAscii end)end;function UpdateComplQAInBridge(self,Q,G,T)if G==nil then return end;local ae=tostring(G)if Q==nil or T==nil then local t=api.get('/devices/'..ae)if t.visible and t.properties.quickAppVariables then Q=t.properties.quickAppVariables;T=t.type end end;if Q and T then UpdateQAInBridge(self,Q,ae,T)table.sort(GlobalHueQAind,function(ac,ad)return ac.descrAscii<ad.descrAscii end)UpdateSelectedHueQA(self,ae,true)end end;function CheckOtherHueMain(self)local aa=api.get('/devices')local ab=tostring(thisDeviceID)for z,t in ipairs(aa)do if t.visible and t.properties.quickAppVariables and tostring(t.id)~=ab then local u={}for z,A in ipairs(t.properties.quickAppVariables)do u[A.name]=A.value end;if u["VersionType"]=="MainHue"and u["HueMagicNumber"]==HueMainMagicNumber then Log(LOG.WARNING,"Hue system can't start - more Hue Main with same HueMagicNumber - QA ID: "..tostring(t.id))return true end end end;return false end;function GetHueParamValue(self,af,ag,ah)if af==nil then return nil end;local H=tostring(af)local t=GlobalHueQA[H]local ai=nil;if t==nil then return nil end;local K=HueBridges[t.bridge].HueIDfromQA[H]if K then local aj;if K=="0"then aj=HueBridges[t.bridge].ActDataGroup0Json else if HueBridges[t.bridge].ActDataJson then aj=HueBridges[t.bridge].ActDataJson[K]end end;if aj and aj[ag]~=nil and aj[ag][ah]~=nil then ai=aj[ag][ah]end end;return ai end;function GetHueParamValueTrans(self,af,ag,ah)if af==nil then return nil end;local H=tostring(af)local t=GlobalHueQA[H]if t==nil then return nil end;if HueBridges[t.bridge].TypeOfBridge=="lgroups"and ag=="state"then ag="action"end;local ai=GetHueParamValue(self,H,ag,ah)return ai end;function LanguageSetupForQAs(self,H,ak,al,am)if H==nil or ak==nil or al==nil then return end;local an=tostring(H)local ao=tostring(ak)if al[ao]==nil then return end;local ap=0;local t=api.get('/devices/'..an)if t then if tostring(t.id)==an then local aq,ar;for as,at in pairs(t.properties.viewLayout["$jason"].body.sections.items)do aq=al[ao][at.components[1].name]if aq then ar=am[at.components[1].name]if ar then aq=(ar.." "..aq):gsub("%s"," ")end;if aq~=at.components[1].text then t.properties.viewLayout["$jason"].body.sections.items[as].components[1].text=aq;ap=ap+1 end end;if at.components[1].components then for au,av in pairs(at.components[1].components)do aq=al[ao][av.name]if aq then ar=am[av.name]if ar then aq=(ar.." "..aq):gsub("%s"," ")end;if aq~=t.properties.viewLayout["$jason"].body.sections.items[as].components[1].components[au].text then t.properties.viewLayout["$jason"].body.sections.items[as].components[1].components[au].text=aq;ap=ap+1 end end end end end end end;if ap>0 then local aw,ai=api.put('/devices/'..an,t)local a7=tostring(fibaro.getRoomNameByDeviceID(tonumber(an))).."-"..tostring(fibaro.getName(tonumber(an)))if ai>201 then Log(LOG.ERROR,"Changed - Err - "..tostring(ap).." language descriptions in QA device: "..a7 .."  %s,RES:%s",json.encode(aw),json.encode(ai))else Log(LOG.LOG,"Changed "..tostring(ap).." language descriptions in QA device: "..a7)end;return ap end end;function UpdateAllLanguageDescriptionsInQAs(self)Log(LOG.LOG,"Update all language descriptions in Hue QAs - start")for J,t in pairs(GlobalHueQA)do if HueBridges[t.bridge].TypeOfBridge=="lgroups"or HueBridges[t.bridge].TypeOfBridge=="lights"then LanguageSetupForQAs(self,J,LanguageQA,LanguageDefLights,DescriptionAddLights)elseif HueBridges[t.bridge].TypeOfBridge=="sensors"then LanguageSetupForQAs(self,J,LanguageQA,LanguageDefSensors,DescriptionAddSensors)end end;Log(LOG.LOG,"Update all language descriptions in Hue QAs - end")end;function startRunScenes(self)local ax=""for ay,z in pairs(HueBridges)do if not HueBridges[ay].SceneInitDone and not HueBridges[ay].SceneInitRun and ax==""then ax=ay;HueBridges[ax].SceneInitRun=true;InitScenesAndLightsToGroups(self,ax,0)if HueBridges[ax].TypeOfBridge=="lgroups"and HueBridges[ax].QAfromHueID["0"]then InitScenesAndLightsToGroup0(self,ax,0)end end end end;function startRunBridges(self)for ay,z in pairs(HueBridges)do if not HueBridges[ay].SceneInitDone then fibaro.setTimeout(2000,function()startRunBridges(self)end)return end end;local ax=""for ay,z in pairs(HueBridges)do if not HueBridges[ay].BridgeInitDone and not HueBridges[ay].BridgeInitRun and ax==""then ax=ay;HueBridges[ax].BridgeInitRun=true;if HueBridges[ax].QAfromHueID["0"]then UpdateHueGroup0(self,ax,0)end;if HueBridges[ax].UpdateID then fibaro.clearTimeout(HueBridges[ax].UpdateID)end;HueBridges[ax].UpdateID=fibaro.setTimeout(CallWait,function()UpdateHue(self,ax)end)end end end;function updateGlobalStatusMessage(self,az)if az==GlobalStatusMessage then return end;GlobalStatusMessage=az;Log(LOG.LOG,az)self:myUpdateLabelView("lblStatus","text",az)self:updateProperty("log",az)end;function main(self)Log(LOG.SYS,"QA for Hue support (main device) - HC3 - version: "..self:getVariable("VersionNumber").." "..self:getVariable("VersionDate"))math.randomseed(os.time()*100000)stopUpdateBridges=true;updateGlobalStatusMessage(self,"Hue system starting - step 3")initUpdateApp_QAHue(self)updateGlobalStatusMessage(self,"Hue system starting - step 4")SetGlobalVar(self)updateGlobalStatusMessage(self,"Hue system starting - step 5")CreateListofHueBridges(self)updateGlobalStatusMessage(self,"Hue system starting - step 6")UserHueBridgesDefinitions(self)updateGlobalStatusMessage(self,"Hue system starting - step 7")IconsForHueQA(self)updateGlobalStatusMessage(self,"Hue system starting - step 8")self:updateLabelEmptyBridge()updateGlobalStatusMessage(self,"Hue system starting - step 9")CreateListofHueDev(self)updateGlobalStatusMessage(self,"Hue system starting - step 10")self:updateLabelBridge()updateGlobalStatusMessage(self,"Hue system starting - step 11")self:updateLabelUpdateQA()updateGlobalStatusMessage(self,"Hue system starting - step 12")UpdateAllLanguageDescriptionsInQAs(self)updateGlobalStatusMessage(self,"Hue system starting - step 13")fibaro.setTimeout(CallWait,function()startRunScenes(self)end)updateGlobalStatusMessage(self,"Hue system starting - step 14")fibaro.setTimeout(CallWait,function()startRunBridges(self)end)updateGlobalStatusMessage(self,"Hue system starting - step 15")InfoInitBridges(self)end;function QuickApp:HueCommands(aA)if not RunQAInit and not RunQA then StartInit(self)end;if not RunHueMain then Log(LOG.WARNING,"MainHue not started yet! ("..tostring(aA)..")")return end;local aB=tsc(aA)fibaro.setTimeout(CallWait,function()HueCommandsStart(self,aB)end)end;function HueCommandsStart(self,aA)function CalcBri(aC)local aD=math.floor(aC*2.54)if aD<2 then aD=254 end;return aD end;local aB=tsc(aA)if aB.time then local aE=os.time()-aB.time;Log(LOG.TRACE,"HueCommands args="..tostring(aB).." - Delivered: "..tostring(aE).."s")else Log(LOG.LOG,"HueCommands args="..tostring(aB))end;if aB.deviceID==nil then return end;local a7=tostring(fibaro.getRoomNameByDeviceID(tonumber(aB.deviceID))).."-"..tostring(fibaro.getName(tonumber(aB.deviceID)))if GlobalHueQA[tostring(aB.deviceID)]==nil then SetCommonErrorsHueDev(self,tostring(aB.deviceID),"HueCommands - ERR - not registered device or not working Main Hue: "..a7,LOG.WARNING,false)return end;if aB.type=="Hue"then if aB.action=="on"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"transitiontime":'..(aB.transitiontime or 0)..',"on": true}'})end)elseif aB.action=="on_bri"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"transitiontime":'..(aB.transitiontime or 0)..',"bri":'..CalcBri(aB.value)..',"on": true}'})end)elseif aB.action=="off"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"transitiontime":'..(aB.transitiontime or 0)..',"on": false}'})end)elseif aB.action=="brightness"then local aD=math.floor(aB.value*2.54)local aF="true"if aD<1 then aF="false"end;fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on":'..aF..',"transitiontime":'..(aB.transitiontime or 0)..',"bri":'..aD..'}'})end)elseif aB.action=="set"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue=aB.hueData})end)elseif aB.action=="setcolor"then local aG=FavouriteColor[aB.typebutton]if aG then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{'..aG..',"transitiontime":'..(aB.transitiontime or 0)..'}'})end)end elseif aB.action=="setbutton"then local aH=FavouriteButton[aB.typebutton]if aH then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{'..aH..',"transitiontime":'..(aB.transitiontime or 0)..'}'})end)end elseif aB.action=="setownbutton"then if aB.command then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{'..aB.command..',"transitiontime":'..(aB.transitiontime or 0)..'}'})end)end elseif aB.action=="toggle"then fibaro.setTimeout(CallWait,function()ActionToggle(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,TransitionTime=aB.transitiontime,UseOldData=true})end)elseif aB.action=="toggle_bri"then fibaro.setTimeout(CallWait,function()ActionToggle(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,TransitionTime=aB.transitiontime,Brightness=CalcBri(aB.value),UseOldData=true})end)elseif aB.action=="toggle2"then fibaro.setTimeout(CallWait,function()ActionToggle(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,TransitionTime=aB.transitiontime})end)elseif aB.action=="toggle_bri2"then fibaro.setTimeout(CallWait,function()ActionToggle(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,TransitionTime=aB.transitiontime,Brightness=CalcBri(aB.value)})end)elseif aB.action=="color"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"transitiontime":'..(aB.transitiontime or 0)..',"hue":'..math.floor(aB.value*655.35)..'}'})end)elseif aB.action=="saturation"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"transitiontime":'..(aB.transitiontime or 0)..',"sat":'..math.floor(aB.value*2.54)..'}'})end)elseif aB.action=="colortemp"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"transitiontime":'..(aB.transitiontime or 0)..',"ct":'..math.floor(math.abs(aB.value-100)*3.47+153)..'}'})end)elseif aB.action=="colorRGB"then if aB.colorR==0 and aB.colorG==0 and aB.colorB==0 and aB.colorW==0 then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"transitiontime":'..(aB.transitiontime or 0)..',"on": false}'})end)else fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"transitiontime":'..(aB.transitiontime or 0)..',"bri":'..CalcBri(aB.value)..',"xy":['..ConvertHueRGBtoXY(aB.colorR,aB.colorG,aB.colorB)..']}'})end)end elseif aB.action=="colorloopstart"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "colorloop"}'})end)elseif aB.action=="colorloopstart_bri"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "colorloop","bri":'..CalcBri(aB.value)..'}'})end)elseif aB.action=="colorloopstop"then ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "none"}'})elseif aB.action=="colorlooptoggle"then if GetHueParamValueTrans(self,aB.deviceID,"state","effect")=="none"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "colorloop"}'})end)else ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "none"}'})end elseif aB.action=="colorlooptoggle_bri"then if GetHueParamValueTrans(self,aB.deviceID,"state","effect")=="none"then fibaro.setTimeout(CallWait,function()ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "colorloop","bri":'..CalcBri(aB.value)..'}'})end)else ActionPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"on": true,"effect": "none"}'})end elseif aB.action=="alertstart"then fibaro.setTimeout(CallWait,function()ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="START",Color=aB.color})end)elseif aB.action=="alerttoggle"then local aC=GetHueParamValueTrans(self,aB.deviceID,"state","alert")if aC then if aC=="none"then fibaro.setTimeout(CallWait,function()ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="START",Color=aB.color})end)else ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="STOP"})end else if GlobalHueQA[aB.deviceID].Alert then ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="STOP"})else fibaro.setTimeout(CallWait,function()ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="START",Color=aB.color})end)end end elseif aB.action=="alertstart2colors"then fibaro.setTimeout(CallWait,function()ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="START",Color=aB.color,Color2=aB.color2})end)elseif aB.action=="alerttoggle2colors"then if GetHueParamValueTrans(self,aB.deviceID,"state","alert")=="none"then fibaro.setTimeout(CallWait,function()ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="START",Color=aB.color,Color2=aB.color2})end)else ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="STOP"})end elseif aB.action=="alertstop"then ActionAlertPUT(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,Alert="STOP"})elseif aB.action=="loopbristart"then fibaro.setTimeout(CallWait,function()ActionPUT_loopChangeLightBri(self,aB.deviceID,"START",CalcBri(aB.value),aB.step,aB.repeattime,aB.maxrepeat,"0")end)elseif aB.action=="loopbristop"then ActionPUT_loopChangeLightBri(self,aB.deviceID,"STOP")elseif aB.action=="setscene"then fibaro.setTimeout(CallWait,function()ActionScenePUT_QAHue(self,{DeviceID=aB.deviceID,BridgeName=aB.bridgeName,ParamHue='{"transitiontime":'..(aB.transitiontime or 0)..',"scene": "'..aB.value..'"}'})end)elseif aB.action=="backup"then fibaro.setTimeout(CallWait,function()BackupStateHueQA(self,aB.deviceID)end)elseif aB.action=="recover"then fibaro.setTimeout(CallWait,function()RecoverStateHueQA(self,aB.deviceID)end)else Log(LOG.WARNING,"HueCommands - ERR - Unknown command "..tostring(aB.action).." - "..a7)end elseif aB.type=="HueQA"then if aB.name=='updateFullQA'then fibaro.setTimeout(CallWait,function()UpdateComplQAInBridge(self,aB.QAvariables,aB.deviceID,aB.QAtype)end)elseif aB.name=='scenesrefresh'then fibaro.setTimeout(CallWait,function()UpdateScenesInQA(self,aB.deviceID)end)elseif aB.name=='updatescenesinQAs'then fibaro.setTimeout(CallWait,function()UpdateAllScenesInQAs(self,aB.bridgeName)end)elseif aB.name=='updateQA'then fibaro.setTimeout(CallWait,function()UpdateSelectedHueQA(self,aB.deviceID,true)end)elseif aB.name=='updateVariablesQA'then fibaro.setTimeout(CallWait,function()UpdateComplQAInBridge(self,aB.QAvariables,aB.deviceID,aB.QAtype)end)else Log(LOG.WARNING,"HueCommands - ERR - Unknown command "..tostring(aB.action).." - "..a7)end else Log(LOG.WARNING,"HueCommands - ERR - Unknown type of command "..tostring(aB.type).." - "..a7)end end;function AllowUpdateBridges(self)stopUpdateBridges=false end;function InfoInitBridges(self)local aI=0;local aJ=0;for ay,z in pairs(HueBridges)do aJ=aJ+2;if HueBridges[ay].BridgeInitDone==true then aI=aI+1 end;if HueBridges[ay].SceneInitDone==true then aI=aI+1 end end;if aJ==0 then updateGlobalStatusMessage(self,"No bridges defined - end!")else updateGlobalStatusMessage(self,"Hue bridges - starting: "..tostring(math.floor(aI/aJ*100+0.5)).."%")if aI<aJ then fibaro.setTimeout(500,function()InfoInitBridges(self)end)else RunHueMain=true;updateGlobalStatusMessage(self,"Hue system running")RunTimeStart=os.time()fibaro.setTimeout(500,function()RunUpdateTimer(self)end)stopUpdateBridges=false;PowerConsumptionMainHue(self)self:updateLabelBridge()self:updateLabelUpdateQA()self:updateLabelEmptyBridge()fibaro.setTimeout(2000,function()self:testFunctions()end)Log(LOG.LOG,"Mem before garbage: "..tostring(collectgarbage("count")))collectgarbage("collect")Log(LOG.LOG,"Mem after garbage: "..tostring(collectgarbage("count")))end end end;function QuickApp:powerUpdate(aK)local aD=tostring(aK):gsub("__"," ")if tonumber(aD)then Log(LOG.LOG,"MainHue - powerUpdate: "..aD)local aL=tonumber(aD)self:updateProperty("power",aL)self:updateProperty("value",aL)aD=string.format("%0.1f",aL)self:myUpdateLabelView("lblPowerCons","text",aD.." W")end end;function StartQA(self)RunHueMain=false;RunTimeStart=nil;stopUpdateBridges=false;self:updateProperty("power",0)self:updateProperty("value",0)GlobalSumPwr=0;self:myUpdateLabelView("lblPowerCons","text","0 W")local aM=tostring(os.date("%d.%m.%Y %H:%M:%S"))self:myUpdateLabelView("lblLastUpdate","text",aM:gsub("%s","__"))for ay,z in pairs(HueBridges)do if HueBridges[ay].UpdateID then fibaro.clearTimeout(HueBridges[ay].UpdateID)end end;CheckNewVersionHueMain(self,nil,0)if CheckOtherHueMain(self)then updateGlobalStatusMessage(self,"Hue system can't start - more Hue Main with same HueMagicNumber")else fibaro.setTimeout(CallWait,function()main(self)end)end end;function QuickApp:testFunctions()end;function StartInit(self)if RunQAInit then return end;RunQAInit=true;RunTimeStart=nil;GlobalStatusMessage=""if self:getVariable("VersionNumber")~=_HueMainQAVersionNumber then self:setVariable("VersionNumber",_HueMainQAVersionNumber)end;if self:getVariable("VersionDate")~=_HueMainQAVersionDate then self:setVariable("VersionDate",_HueMainQAVersionDate)end;if self:getVariable("VersionType")~=_HueMainQAVersionType then self:setVariable("VersionType",_HueMainQAVersionType)end;local aN=self:getVariable("HueMagicNumber")if aN and tostring(aN):lower()~="none"and aN~="A24Uj8756"then HueMainMagicNumber=tostring(aN)end;Log(LOG.HEADER,"HUE MAIN QA - version: "..tostring(_HueMainQAVersionNumber).." ".._HueMainQAVersionDate.." ".._HueMainQAVersionType)Log(LOG.LOG,"onInit - start")thisDeviceID=tonumber(plugin.mainDeviceId)Log(LOG.LOG,"This device ID: "..thisDeviceID.." Hue Magic Number: "..HueMainMagicNumber)GlobalLogs=false;local aO=self:getVariable("Logs")if aO then local a8=string.lower(tostring(aO))if a8=="yes"or a8=="y"then GlobalLogs=true end end;GlobalShowBulbs=false;aO=self:getVariable("ShowBulbs")if aO then local a8=string.lower(tostring(aO))if a8=="yes"or a8=="y"then GlobalShowBulbs=true end end;local aP=self:getVariable("UpdatePower")if aP and tonumber(aP)and tonumber(aP)>=1 then PowerUpdateInterval=tonumber(aP)else PowerUpdateInterval=nil end;DefLabelsSetup()self:myUpdateLabelView("lblVersion","text",tostring(_HueMainQAVersionNumber).." "..tostring(_HueMainQAVersionDate))self:updateProperty("power",0)self:updateProperty("value",0)self:myUpdateLabelView("lblPowerCons","text","0 W")updateGlobalStatusMessage(self,"Hue system starting - step 1")if CheckContinueMainUpdate(self)then updateGlobalStatusMessage(self,"Hue system starting - step 2")local aM=tostring(os.date("%d.%m.%Y %H:%M:%S"))self:myUpdateLabelView("lblLastUpdate","text",aM:gsub("%s","__"))CheckNewVersionHueMain(self,nil,0)AutoUpdateTimer(self,true)GetSystemEvents(self)if HC3version()<a then updateGlobalStatusMessage(self,"Hue system can't start - you have unsupported HC3 version")elseif CheckOtherHueMain(self)then updateGlobalStatusMessage(self,"Hue system can't start - more Hue Main with same HueMagicNumber")else fibaro.setTimeout(CallWait,function()main(self)end)end end;Log(LOG.LOG,"onInit - end")RunQA=true end;function QuickApp:onInit()local a8="Waiting after restart ..."self:updateView("lblStatus","text",a8)RunTimeStart=nil;GlobalStatusMessage=" "self:updateProperty("log",a8)self:updateProperty("power",0)self:updateProperty("value",0)setUpUtilities(self)self.debug=function(self,...)Log(LOG.LOG,...)end;fibaro.setTimeout(10000,function()StartInit(self)end)end